#include "Buffer.h"
#include <cassert>
#include <cstddef>
#include <sys/uio.h>
#include <iostream>

Buffer::Buffer(size_t size)
: _buffer(kCheapPrepend + kInitialSize)
, _readerIndex(kCheapPrepend)
, _writerIndex(kCheapPrepend)
{
    assert(readableBytes() == 0);
    assert(writableBytes() == size);
    assert(prependableBytes() == kCheapPrepend);
}
ssize_t Buffer::readFd(int fd)
{
    char extrabuf[65536];
    struct iovec vec[2];
    /*从fd上读数据到 栈缓冲extrabuf 和 _writerIndex*/
    //iov_base存数据 iov_len大小
    const size_t writable = writableBytes();
    vec[0].iov_base = begin() + _writerIndex;
    vec[0].iov_len = writable;
    vec[1].iov_base = extrabuf; 
    vec[1].iov_len = sizeof extrabuf; 
        /* std::cout << "[Buffer] Before readToBuffer - readable: " << readableBytes() */
        /*       << ", writable: " << writable << std::endl; */

    //_buffer大小足够则不写入extrabuf
    const int iovcnt = (writable < sizeof extrabuf) ? 2 : 1;
    const ssize_t n = ::readv(fd, vec, iovcnt);
    if((size_t)n <= writable) //<buffersize 更改writerIndex
    {
        _writerIndex += n;
    }
    else
    {
        /*buffer空间不足 写入到extrabuf _writerIndex到尾部*/
        _writerIndex = _buffer.size();
        append(extrabuf, n - _writerIndex);
         /* std::cout << "[Buffer] Data overflow to extrabuf, total " << n << " bytes" */
         /*              << " (buffer: " << writable << ", extrabuf: " << n - writable << ")" << std::endl; */
    }
    return n;
}

void Buffer::append(const char* data, size_t len)
{
    ensureWriteBytes(len);
    std::copy(data, data + len, beginWrite());
    hasWritten(len);
}
void Buffer::ensureWriteBytes(size_t len)
{
    if(writableBytes() < len)
    {
        makeSpace(len); //扩容
    }
    assert(writableBytes() >= len);
}
void Buffer::makeSpace(size_t len)
{
    // 检查_readerIndex前面的空间大小是否足够
    if(writableBytes() + prependableBytes() < len + kCheapPrepend)
    { //不够直接resize扩容
        _buffer.resize(_writerIndex+len);
    }
    else
    {//可读数据移动到前面
        assert(kCheapPrepend < _readerIndex);
        size_t readable = readableBytes();
        std::copy(begin()+_readerIndex, begin()+_writerIndex, begin()+kCheapPrepend);
        //重置可读
        _readerIndex = kCheapPrepend;
        _writerIndex = _readerIndex + readable;
        assert(readable == readableBytes());
    }
}
